if (document.implementation && document.implementation.createDocument) {

Concentre.Factory.Xml = {
	 	isWs : function  (node) {
			return !(/[^\r\t\n ]/.test(node.data));
		},

		copyNameSpaces : function (el) {
        	for (var n in concentre.namespaceNodes) {
                var ns = concentre.namespaceNodes[n];
          		var prefix = 'xmlns:'+ ns.prefix;

          		if (ns.prefix=='xml' || ns.prefix=='xmlns' || ns.prefix=='') continue;
                if (el.getAttribute(prefix)==null) el.setAttribute(prefix,ns.namespaceURI);
    	    }
		},
	
		isIgnorable : function (node) {
			return node.nodeType==8 || (node.nodeType==3 && this.isWs(node));
		},
	
		firstChild : function (node) {
			var n = node.firstChild;
			while (n) {
				if (!this.isIgnorable(n)) return n;
				n = n.nextSibling;				
			}
		},

		replace: function (source,target) {
			var s = new XMLSerializer();
			for (var c = source.firstChild; c.nodeType!=1; c = c.nextSibling) {}
		 	var str = s.serializeToString(c);
		 
		 	target.parentNode.replaceChild(source.firstChild, target);
		 	target.innerHTML = str;
		},
	
		load : function (source) {
			assert(window.DOMParser);
			var doc = new DOMParser().parseFromString(source, "text/xml");
			var expr = new XPath('/*/text()');
			
			if (doc.documentElement.namespaceURI == "http://www.mozilla.org/newlayout/xml/parsererror.xml") { 
   				throw new Exception(XPath.string(expr(doc.documentElement)));
 			}
			
 			return doc;
 		
		},
	
 		loadURL : function (url) {
	
			var httpRequest = new XMLHttpRequest();
			httpRequest.open('GET',url, false);
			httpRequest.send(null);
			
			switch (httpRequest.status) {
				case 0:
				case 200:
					return this.load(httpRequest.responseText);		
					break;
				default:
					throw new Exception('HTTP/1.1 ' + httpRequest.status + ' ' + httpRequest.statusText + '\n' + uri);
			}	
		
			httpRequest = null;
			return null;
		},
		
		toString: function () {
			return '[ Object Concentré Factory Xml ]';
		},
		
		serialize: function(source) {
			var s = new XMLSerializer();
			for (var n = source.firstChild; n.nodeType!=1; n = n.nextSibling) {}
		 	return s.serializeToString(n);
		}
	
};

} else  if (typeof(window.ActiveXObject) != "undefined") {

_DOM_PROGID = pickRecentProgID(["Msxml2.DOMDocument.5.0", "Msxml2.DOMDocument.4.0", "Msxml2.DOMDocument.3.0", "MSXML2.DOMDocument","MSXML.DOMDocument", "Microsoft.XMLDOM"]);
_XMLHTTP_PROGID = null; 
_THREADEDDOM_PROGID = pickRecentProgID(["MSXML2.FreeThreadedDOMDocument.6.0", "Msxml2.FreeThreadedDOMDocument.5.0", "MSXML2.FreeThreadedDOMDocument.4.0", "MSXML2.FreeThreadedDOMDocument.3.0"]);
_XSLTEMPLATE_PROGID = pickRecentProgID(["Msxml2.XSLTemplate.6.0","Msxml2.XSLTemplate.5.0", "Msxml2.XSLTemplate.4.0", "MSXML2.XSLTemplate.3.0"]);	
_DOM_XMLWRITER = pickRecentProgID(["Msxml2.MXXMLWriter.6.0","Msxml2.MXXMLWriter.5.0", "Msxml2.MXXMLWriter.4.0", "Msxml2.MXXMLWriter.3.0", "MSXML2.MXXMLWriter", "MSXML.MXXMLWriter", "Microsoft.XMLDOM"]);


_IS_MSXML_5 = _DOM_PROGID == 'Msxml2.DOMDocument.5.0';

function pickRecentProgID(idList){
  // found progID flag
	while (idList.length > 0) {
			try {
  		 	new ActiveXObject(idList[0]);	
  		 	return idList[0];
			} catch (e) {
  			// Didn't work. Try the next program.
  			idList.shift();
			}
	}
 	throw new Exception("Could not retreive a valid progID of Class");
};

	if(!window.XMLHttpRequest){
		function XMLHttpRequest(){
			if (!_XMLHTTP_PROGID) {
				_XMLHTTP_PROGID = pickRecentProgID(["Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.5.0", "Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"]);
			}
    	return new ActiveXObject(_XMLHTTP_PROGID);
	}
		
}

function XSLTProcessor(){
   this.template = new ActiveXObject(_XSLTEMPLATE_PROGID);
   this.processor = null;
};

XSLTProcessor.prototype.importStylesheet = function(xslDoc){
    
		xslDoc.setProperty("SelectionLanguage", "XPath");
    xslDoc.setProperty("SelectionNamespaces", "xmlns:xsl='http://www.w3.org/1999/XSL/Transform'");
    
    // convert stylesheet to free threaded
    var converted = new ActiveXObject(_THREADEDDOM_PROGID);
    // make included/imported stylesheets work if exist and xsl was originally loaded from url
    if(xslDoc.url && xslDoc.selectSingleNode("//xsl:*[local-name() = 'import' or local-name() = 'include']") != null){
        converted.async = false;
        converted.load(xslDoc.url);
    } else {
        converted.loadXML(xslDoc.xml);
    };
    
    this.template.stylesheet = converted;
    
    this.processor = this.template.createProcessor();
    // (re)set default param values
    this.paramsSet = new Array();
};


XSLTProcessor.prototype.transformToDocument = function(sourceDoc){
        
        var outDoc;
        if(_THREADEDDOM_PROGID){
            this.processor.input=sourceDoc;
            outDoc=new ActiveXObject(_DOM_PROGID);
            this.processor.output=outDoc;
            this.processor.transform();
            return outDoc;
        }
        else{
            this.processor.input = sourceDoc;
            outDoc = new ActiveXObject(_DOM_XMLWRITER);
            this.processor.output = outDoc; 
            this.processor.transform();
            var oDoc = new ActiveXObject(_DOM_PROGID);
            oDoc.loadXML(outDoc.output+"");
            return oDoc;
        }
};

XSLTProcessor.prototype.transformToFragment = function (sourceDoc, ownerDoc) {

		this.processor.input = sourceDoc;
        this.processor.transform();
        
        var s = this.processor.output;
      	var f = ownerDoc.createDocumentFragment();
 		var container;
 	 	
 	 	if (ownerDoc.body && ownerDoc.body.innerHTML) {
            container = ownerDoc.createElement('div');
            container.innerHTML = s;
            f.appendChild(container);
        }	

		return f;
};

XSLTProcessor.prototype.setParameter = function(nsURI, name, value){
    /* nsURI is optional but cannot be null */
    if(nsURI){
        this.processor.addParameter(name, value, nsURI);
    }else{
        this.processor.addParameter(name, value);
    };
};

Concentre.Factory.Xml = {

	isWs : function  (node) {
		return !(/[^\r\t\n ]/.test(node.data));
	},

        copyNameSpaces : function (el) {
        for (var n in concentre.namespaceNodes) {
                var ns = concentre.namespaceNodes[n];
          var prefix = 'xmlns:'+ ns.prefix;

          if (ns.prefix=='xml' || ns.prefix=='xmlns' || ns.prefix=='') continue;

                if (el.getAttribute(prefix)==null) el.setAttribute(prefix,ns.namespaceURI);
	  }
        },
	
	isIgnorable : function (node) {
		return node.nodeType==8 || (node.nodeType==3 && Concentre.Factory.Xml.isWs(node));
	},

	firstChild : function (node) {
			var n = node.firstChild;
			while (n) {
				if (!Concentre.Factory.Xml.isIgnorable(n)) return n;
				n = n.nextSibling;				
			}
	},
	
	serialize:  function (node) {
		return node.firstChild.xml;
	},
	
	clean : function( source ) { 
		source = source.replace(/<!DOCTYPE[^>]*>/, "");
		return source;
	},

	replace: function (source, target) {
		var d = source.documentElement;
		var r = new RegExp('<\/?'+ d.nodeName +'[^>]*>','gi');
		target.innerHTML = d.xml.replace(r,'');
	},
	
	load : function (source) {
		var source = Concentre.Factory.Xml.clean(source);

		assert(window.ActiveXObject);
		var doc = new ActiveXObject(_THREADEDDOM_PROGID);
	
		doc.setProperty("NewParser", true);
		doc.validateOnParse = false;
		doc.preserveWhiteSpace = false;
		doc.loadXML(source);
		
		if (doc.parseError.errorCode != 0) throw new Exception(doc.parseError.reason, doc.parseError);
		return doc;
	},

	loadURL : function (uri) {
		var httpRequest = new XMLHttpRequest();
		httpRequest.open('GET',uri, false);
		httpRequest.send(null);
			
		switch (httpRequest.status) {
			case 0:
			case 200:
				return Concentre.Factory.Xml.load(httpRequest.responseText);		
				break;
			default:
				throw new Exception('HTTP/1.1 ' + httpRequest.status + ' ' + httpRequest.statusText + '\n' + uri);
		}
		
		httpRequest = null;
		return null;
	}
	
};

}
